package cn.lhl.flowable.workflow;

import org.flowable.bpmn.model.*;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class LCQingJia {
    private static String deploymentName = "员工请假流程";
    @Resource
    private ProcessEngine processEngine;
    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;

    @Resource
    private DynamicBpmnService dynamicBpmnService;


    /**
     * 部署
     */
    public void Deployment() {
        //获取Flowable服务
        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 查询deploymentName("员工请假流程")的
        Deployment singleResult = repositoryService.createDeploymentQuery().deploymentName(deploymentName).singleResult();

        if (null != singleResult) {
            //删除部署的流程  会删除流程和部署的信息  true 加上历史 和任务
            repositoryService.deleteDeployment(singleResult.getId(), true);

            //更新
            //repositoryService.changeDeploymentParentDeploymentId(singleResult.getId());

        }


        //部署流程定义  会创建流程 和部署信息  addClasspathResource 不再接受key 和 那么 会使用 Resource 中的
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("processes/员工请假流程.bpmn20.xml") //资源路径
                .name(deploymentName)//javaboy的工作流名称
                .category("请假")//javaboy的工作流分类
                .deploymentProperty("haha","tyuio")
                .key("javaboy的工作流key")//javaboy的工作流key
                .deploy();


        // ===========================================
        //查询全部的流程
        List<ProcessDefinition> list1 = repositoryService.createProcessDefinitionQuery().list();
        //遍历方法二：
        System.out.println("全部的流程>>>>>>>" + list1.size());
        list1.forEach(System.out::println);
        //System.out.println("全部的流程>>>>>>>"+ list1.size());

        //查询全部的 部署信息
        List<Deployment> list = repositoryService.createDeploymentQuery().list();

        System.out.println("全部的部署信息>>>>>>>" + list.size());
        list.forEach(System.out::println);

        //通过资源name查流程
        List<ProcessDefinition> processDefinitionList = repositoryService.createProcessDefinitionQuery()
                .processDefinitionName("ttttt")
                .list();

        System.out.println("通过资源Name 查流程 ttttt >>>>" + processDefinitionList.size());

        List<ProcessDefinition> processDefinitionList2 = repositoryService.createProcessDefinitionQuery()
                .processDefinitionResourceName("processes/员工请假流程.bpmn20.xml")
                .list();

        System.out.println("通过资源ResourceName查流程 >>>>" + processDefinitionList2.size());
        processDefinitionList.forEach(System.out::println);

        //通过资源id id="LCQingJia"  id 会放到key中
        List<ProcessDefinition> processDefinitionList_id = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("LCQingJia")
                .list();

        System.out.println("通过资源<process id=\"LCQingJia\"  查流程 processDefinitionKey >>>>" + processDefinitionList.size());
        processDefinitionList_id.forEach(System.out::println);


    }


    /**
     * 启动流程
     *
     * @param variables
     */
    @Transactional
    public void start(Map<String, Object> variables) {

        // LCQingJia是流程xml文件的 process id
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("LCQingJia", variables);
        String pid = processInstance.getId();
        System.out.println("pid:" + pid);
    }


    /**
     * 部门经理查看任务
     *
     * @return
     */
    public List<String> daiban() {

        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("mageger2")
                .orderByTaskCreateTime() // 按照任务创建时间
                .desc() // 倒序排列
                .list();

        List<String> retList = new ArrayList<>();
        for (int i = 0; i < tasks.size(); i++) {
            Task task = tasks.get(i);

            //根据任务Id查询特定流程实例的变量
            Map<String, Object> processVariables = taskService.getVariables(task.getId());
            System.out.println("根据任务Id查询特定流程实例的变量>>" + processVariables);

            String msg = String.format("pid:%s,task_name:%s,tid:%s，task_key:%s,Variables:%s",
                    task.getProcessInstanceId(),
                    task.getName(),
                    task.getId(),
                    task.getTaskDefinitionKey(),
                    processVariables
            );

            retList.add(msg);
        }
        return retList;
    }

    /**
     * 部门经理同意
     */
    public void tongyi() {
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("mageger2")
                .orderByTaskCreateTime() // 按照任务创建时间
                .desc() // 倒序排列
                .list();

        if (tasks.size() <= 0) {
            System.out.println("无任务tasks");
            return;
        }

        Map variables = new HashMap<String, Object>();
        // approved 是流程定义中的值，不能改动
        variables.put("excl_approved", 1);

        String tid = tasks.get(0).getId();
        // 传入tid
        taskService.complete(tid, variables);
        System.out.println("tongyi>>>tid:" + tid);
    }


    public void chaLiShiLiuCheng() {

        System.out.println("历史的流程>>>>");
        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().finished()
                .orderByProcessInstanceEndTime()
                .desc()
                .list();

        list.forEach(System.out::println);

    }

    public void chaLiShiTask(String candidateGroup) {
        System.out.println("历史的Task>>>>");
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().finished().taskCandidateGroup(candidateGroup)
                .orderByHistoricTaskInstanceEndTime()
                .desc()
                .list();

        list.forEach(System.out::println);

    }
    /**
     * 部门经理拒绝
     */
    public void jujue() {
//        获取最新的task id
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers")
                .orderByTaskCreateTime()
                .desc()
                .list();
        String taskId = tasks.get(0).getId();
        Map variables = new HashMap<String, Object>();
        variables.put("approved", false);
//        传入tid
        taskService.complete(taskId, variables);
    }


    /**
     * 查下一个审批节点信息
     */
    public void nextNodeOfTodo() {

        // 存储当前节点的下一环节的所有用户节点
        ArrayList<UserTask> userTaskList = new ArrayList<>();

        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("mageger2")
                .orderByTaskCreateTime() // 按照任务创建时间
                .desc() // 倒序排列
                .list();

        if(tasks.size()<=0){
            return;
        }

        //Task currentTask = taskService.createTaskQuery().taskId("").singleResult(); // 获取当前任务
        Task currentTask =tasks.get(0);
        //获取Flowable服务
        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 查询processDefinitionId("员工请假流程")的
        ProcessDefinition lcQingJia = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("LCQingJia")
                .singleResult();

        //获取流程定义id
        //String definitionId = runtimeService.createProcessInstanceQuery().processInstanceId(lcQingJia.getId()).singleResult().getProcessDefinitionId();


        //获取bpmn对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(lcQingJia.getId());

        Execution execution = runtimeService.createExecutionQuery()
                .executionId(currentTask.getExecutionId()).singleResult();

        //通过节点定义id获取当前节点   execution.getActivityId() 当前节点的id    currentTask.getTaskDefinitionKey()

        //FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(execution.getActivityId());
        //当前节点所有输出顺序流
       // List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows();
        getNextUserTaskList(userTaskList ,bpmnModel ,currentTask.getTaskDefinitionKey());


        System.out.println("nextNodeOfTodo >>>>" + userTaskList.size());
        userTaskList.forEach(System.out::println);

    }


    private void getNextUserTaskList(ArrayList<UserTask> userTaskList, BpmnModel bpmnModel, String currentId) {
        //通过节点定义id获取当前节点
        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(currentId);
        //当前节点所有输出顺序流
        List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows();

        FlowElement targetFlowElement = null;
        for (SequenceFlow outgoingFlow : outgoingFlows) {


            targetFlowElement = outgoingFlow.getTargetFlowElement();

            //用户节点
            if (targetFlowElement instanceof UserTask) {
                userTaskList.add((UserTask) targetFlowElement);
            } else if (targetFlowElement instanceof EndEvent) {
                // 结束节点
            }else {
                // 没有找到用户节点，且下一节点不是最后一个节点，继续查找
                getNextUserTaskList(userTaskList, bpmnModel, targetFlowElement.getId());
            }
        }
    }

}
